﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace GenericLibrary.Common {


    public class TimePoint : IComparable<TimePoint> {


        private static TimePoint _globalBase = new TimePoint();
        
        private TimePoint _base;
        private double _bias;

        private TimePoint() {
            try {
                this._base = this;
                this._bias = 0;
            } catch( Exception ) {
                Debug.Assert( false );
                throw;
            }
        }

        private TimePoint( TimePoint @base, double bias ) {
            try {
                this._base = @base;
                this._bias = bias;
            } catch( Exception ) {
                Debug.Assert( false );
                throw;
            }
        }

        public static void SetBase( TimePoint @base ) {
            try {
                if( !object.ReferenceEquals( @base, _globalBase ) ) {
                    _globalBase._bias -= @base.Bias;
                    _globalBase._base = @base;
                    @base._bias = 0;
                    @base._base = @base;
                    _globalBase = @base;
                }
            } catch( Exception ) {
                Debug.Assert( false );
                throw;
            }
        }

        public static TimePoint Base {
            get {
                return _globalBase;
            }
        }

        private double Bias {
            get {
                try {
                    while( !object.ReferenceEquals( this._base, _globalBase ) ) {
                        this._bias += this._base._bias;
                        this._base = this._base._base;
                    }
                    return this._bias;
                } catch( Exception ) {
                    Debug.Assert( false );
                    throw;
                }
            }
        }

        #region IComparable<TimePoint> Members

        public int CompareTo( TimePoint other ) {
            try {
                if( object.ReferenceEquals( other, this ) ) {
                    return 0;
                }
                return this.Bias.CompareTo( other.Bias );
            } catch( Exception ) {
                Debug.Assert( false );
                throw;
            }
        }

        #endregion

        public static TimePoint operator +( TimePoint tp, double bias ) {
            if( bias == 0 ) {
                return tp;
            }
            return new TimePoint( tp, bias );
        }

        public static TimePoint operator +( double bias, TimePoint tp ) {
            if( bias == 0 ) {
                return tp;
            }
            return new TimePoint( tp, bias );
        }

        public static double operator -( TimePoint tp1, TimePoint tp2 ) {
            try {
                if( object.ReferenceEquals( tp1, tp2 ) ) {
                    return 0;
                }
                return tp1.Bias - tp2.Bias;
            } catch( Exception ) {
                Debug.Assert( false );
                throw;
            }
        }
    }

    
}
